using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net;
using System.Reflection;
using System.Windows.Forms;

namespace EventHandlerAdmin
{
    public partial class MainForm : Form
    {
        #region Private Data
        private const string LOGIN_URL = "_vti_bin/PSI/loginWindows.asmx";
        private const string EVENTS_URL = "_vti_bin/PSI/events.asmx";
        private bool LoggedIn = false;

        private wsLogin.LoginWindows login = new wsLogin.LoginWindows();
        private wsEvents.Events events = new wsEvents.Events();
        private wsEvents.EventHandlersDataSet dsEventHandlers;
        private wsEvents.EventsDataSet dsEvents;
        #endregion

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                Splash formSplash = new Splash();
                formSplash.Show();
                Application.DoEvents();

                formSplash.FadeForm();
                formSplash.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #region UI Event Handlers
        private void btnLogin_Click(object sender, EventArgs e)
        {
            try
            {
                if (LoggedIn)
                {
                    // Logoff if already logged in.
                    login.Logoff();
                    // Hide the grids and change the button text.
                    dgEvents.Visible = false;

                    btnLogin.Text = "Logon";
                    txtProjectServerURL.Enabled = true;
                    btnBrowse.Enabled = false;
                }
                else
                {
                    Cursor = Cursors.WaitCursor;
                    btnLogin.Enabled = false;
                    btnBrowse.Enabled = true;

                    // Build the URL.
                    if (!txtProjectServerURL.Text.EndsWith("/"))
                    {
                        txtProjectServerURL.Text = txtProjectServerURL.Text + "/";
                    }
                    login.Url = txtProjectServerURL.Text + LOGIN_URL;
                    login.Credentials = CredentialCache.DefaultCredentials;
                    events.Url = txtProjectServerURL.Text + EVENTS_URL;
                    events.Credentials = CredentialCache.DefaultCredentials;

                    // Login to project server.
                    LoggedIn = login.Login();
                    if (LoggedIn) RefreshDataGridView();

                    dsEvents = events.ReadEventsList();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                btnLogin.Enabled = true;
                Cursor = Cursors.Default;
            }
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                txtAssemblyName.Text = openFileDialog.FileName;

                try
                {
                    Cursor = Cursors.WaitCursor;

                    btnLogin.Text = "Logoff";
                    txtProjectServerURL.Enabled = false;

                    // Load the assembly.
                    Assembly loggerAssem = Assembly.LoadFile(txtAssemblyName.Text);
                    lblFullName.Text = loggerAssem.FullName;

                    dgAssemblyHandlers.Rows.Clear();
                    foreach (Type t in loggerAssem.GetTypes())
                    {
                        // Make sure it is an event receiver class.
                        if (t.IsClass && t.BaseType.Module.Name == "Microsoft.Office.Project.Server.Events.Receivers.dll")
                        {
                            foreach (MethodInfo mi in t.GetMethods())
                            {
                                // Make sure only implemented handlers are displayed.
                                if (mi.DeclaringType.FullName == t.FullName)
                                {
                                    int index = dgAssemblyHandlers.Rows.Add();
                                    dgAssemblyHandlers.Rows[index].Cells["ReceiverClass"].Value = t.BaseType.Name;
                                    dgAssemblyHandlers.Rows[index].Cells["ClassName"].Value = t.FullName;
                                    dgAssemblyHandlers.Rows[index].Cells["EventMethod"].Value = mi.Name;
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }


        private void btnAdd_Click(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;

                wsEvents.EventHandlersDataSet eventHandlers = new wsEvents.EventHandlersDataSet();
                foreach (DataGridViewRow dgvr in dgAssemblyHandlers.SelectedRows)
                {
                    string recClass = dgvr.Cells["ReceiverClass"].Value.ToString();
                    string className = dgvr.Cells["ClassName"].Value.ToString();
                    string eventMethod = dgvr.Cells["EventMethod"].Value.ToString();
                    int index = recClass.LastIndexOf("EventReceiver");
                    string sourceName = recClass.Substring(0, index);
                    string eventName = eventMethod.Substring(2);
                    int eventID = GetEventID(sourceName, eventName);

                    if (LoadEventInDataSet(eventID, className, sourceName, eventName, eventHandlers) == false)
                    {
                        MessageBox.Show("Class " + className + ", Method " + eventMethod + " is already installed.");
                    }
                }
                if (eventHandlers.EventHandlers.Rows.Count > 0)
                {
                    events.CreateEventHandlerAssociations(eventHandlers);
                    UnselectHandlers();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Any previously performed operations may not have completed yet.\nPlease refresh to see the current status.\n" + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;

                if (dgEvents.SelectedRows.Count == 0) return;

                Guid[] arr = new Guid[dgEvents.SelectedRows.Count];
                int index = 0;
                foreach (DataGridViewRow dgvr in dgEvents.SelectedRows)
                {
                    arr[index++] = (Guid)dgvr.Cells["EventHandlerUid"].Value;
                }
                events.DeleteEventHandlerAssociations(arr);

                UnselectHandlers();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            RefreshDataGridView();
            Cursor = Cursors.Default;
        }

        private void btnSelect_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow dgvr in dgEvents.Rows)
            {
                dgvr.Selected = true;
            }
        }

        private void btnUnselect_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow dgvr in dgEvents.Rows)
            {
                dgvr.Selected = false;
            }
        }

        private void txtProjectServerURL_TextChanged(object sender, EventArgs e)
        {
            btnLogin.Enabled = txtProjectServerURL.Text.Length > 0;
        }

        private void txtAssemblyName_TextChanged(object sender, EventArgs e)
        {
            btnAdd.Enabled = txtAssemblyName.Text.Length > 0;
        }

        private void dgEvents_SelectionChanged(object sender, EventArgs e)
        {
            btnRemove.Enabled = dgEvents.SelectedRows.Count > 0;
        }

        private void dgAssemblyHandlers_SelectionChanged(object sender, EventArgs e)
        {
            btnAdd.Enabled = dgAssemblyHandlers.SelectedRows.Count > 0;
        }
        #endregion

        #region Helper Methods
        private void RefreshDataGridView()
        {
            // Load the grid with the list of events.
            dsEventHandlers = events.ReadEventHandlerAssociations();
            if (dsEventHandlers != null)
            {
                // Bind the data to the grid.
                dgEvents.DataSource = dsEventHandlers.EventHandlers;

                // Change the column headers.
                dgEvents.Columns["EventId"].HeaderText = "Event ID";
                dgEvents.Columns["ClassName"].HeaderText = "Class Name";
                dgEvents.Columns["AssemblyName"].HeaderText = "Assembly Name";
                dgEvents.Columns["AssemblyName"].DisplayIndex = 6;
                dgEvents.Columns["EventHandlerUid"].HeaderText = "Event Handler UID";
                dgEvents.Columns["EventHandlerUid"].DisplayIndex = 6;
            }
        }

        private bool LoadEventInDataSet(int eventID, string className, string sourceName, string eventName, wsEvents.EventHandlersDataSet newEventHandlers)
        {
            // Make sure the handler is not already installed.
            if (HandlerInstalled(className, eventID)) return false;

            // 0=EventUid, 1=Name, 2=AssemblyName, 3=Class, 4=EventId, 5=Desc, 6=Order
            // First get any existing events to determine the order.  Always make it the last one.
            wsEvents.EventHandlersDataSet ds = events.ReadEventHandlerAssociationsForEvent((wsEvents.PSEventID)eventID);
            int order = 0;
            foreach (DataRow dr in ds.EventHandlers.Rows)
            {
                order = Math.Max(order, (int)dr["Order"]);
            }
            order++;

            // Build the new row for the new logging event handler.
            object[] rowParams = new object[7];
            rowParams[0] = Guid.NewGuid();
            rowParams[1] = className + " " + sourceName + " " + eventName;
            rowParams[2] = lblFullName.Text;
            rowParams[3] = className; 
            rowParams[4] = eventID;
            rowParams[5] = "";
            rowParams[6] = order;
            newEventHandlers.EventHandlers.Rows.Add(rowParams);
            return true;
        }

        private int GetEventID(string sourceName, string eventName)
        {
            DataView dv = new DataView(dsEvents.Event);
            dv.RowFilter = dsEvents.Event.Columns["SourceName"].ColumnName + " = '" + sourceName + "'";
            dv.RowFilter = dv.RowFilter + " AND " + dsEvents.Event.Columns["EventName"].ColumnName + " = '" + eventName + "'";
            if (dv.Count == 0) return -1;
            DataRowView drv = dv[0];
            return (int)drv["EventId"];
        }

        private bool HandlerInstalled(string className, int eventID)
        {
            DataView dv = new DataView(dsEventHandlers.EventHandlers);
            dv.RowFilter = dsEventHandlers.EventHandlers.Columns["ClassName"].ColumnName + " = '" + className + "'";
            dv.RowFilter = dv.RowFilter + " AND " + dsEvents.Event.Columns["EventID"].ColumnName + " = " + eventID;
            return dv.Count > 0;
        }

        private void UnselectHandlers()
        {
            foreach (DataGridViewRow dgvr in dgEvents.SelectedRows)
            {
                dgvr.Selected = false;
            }
        }
        #endregion
    }
}